Análisis exploratorio

Sobre la base:

La base de datos consta de 18 variable, una variable a predecir y 17 candidatas a predictoras. 34209 registros de cada variable.

  1. Loan.Status (VARIABLE DICOTOMA A PREDECIR, VALORES POSIBLES -> [Fully Paid, Charged Off])

Nombre variable | tipo de variable | num valores posibles | valores posibles

  1. Term | nominal | 2 | [“Long Term”, “Short Term”]
  2. Years.in.current.job | ordinal | 12 | [“n/a”, “< 1 year”, “1 year”:“9 years”, “10+ years”]
  3. Home.Ownership | nominal | 4 | [“Rent”, “Home Mortgage”, “Own Home”, “HaveMortgage” ]
  4. Purpose | nominal | 16 | […>15 valores posibles…] | << Requiere homologar como factor “other” and “Other” >>
  5. Current.Loan.Amount | continua | [min -> 21449.74 , mean -> 14044734.38, max -> 100000002.5]
  6. Credit.Score | continua | [min -> 584.00, mean -> 1048.48, max -> 7509.0]
  7. Annual.Income | continua | [min -> 164596.55, mean -> 1441110.95, max -> 30838993.9]
  8. Monthly.Debt | continua | [min -> 0.00, mean -> 19025.56, max -> 229056.4]
  9. Years.of.Credit.History | continua | [min -> 2.30, mean -> 19.21, max -> 59.6]
  10. Months.since.last.delinquent | continua | [min-> 0.00, mean -> 34.96, max -> 178.1] (Meses desde el último moroso)
  11. Number.of.Open.Accounts | continua | [min -> 0.00, mean -> 11.43, max -> 49.0]
  12. Number.of.Credit.Problems | continua | [min -> 0.00, mean -> 0.53, max -> 15.0]
  13. Current.Credit.Balance | continua | [min -> 0.00, mean -> 259532.60, max -> 7140732.6]
  14. Maximum.Open.Credit | continua | [min -> 0.00, mean -> 666270.83, max -> 798255369.7]
  15. Bankruptcies | continua | [min -> 0.00, mean -> 0.46, max -> 7.0]
  16. Tax.Liens | continua | [min -> 0.00, mean -> 0.42, max -> 14.0] (gravámenes fiscales)
  17. ID —- excluir variable de cualquier análisis —-

Conteos: nominal - 3 ordinal - 1 continua - 8

Sobre la variable dependiente y de acuerdo con la siguiente pagina web:

A charge-off is the opposite of paid in full. It means the lender hasn’t received payment for at least 180 days, and the account is in default. The lender, or a third-party collection agency, can still come after this kind of debt. Charge-offs have an extremely negative effect on your credit score.

Fuente: https://budgeting.thenest.com/account-paid-full-vs-chargeoff-23884.html

Objetivos

El presente rmarkdown tiene como objetivo elaborar un análisis exploratorio para el reconocimiento del dataset en la busqueda la lógica del negocio, como de patrones de cumplimiento en las variables a emplear en el modelo de regresión lógistica, así como también proponer limites y filtros a cada variable continua en caso de existir valores presuntamente atipicos. Estas propuestas de filtros se evaluaran y se propondran en el análisis univariado y serán valorados al final del rmarkdown para generar 2 muestras (muestra completa y submuestra 1) con las que en cada una se ajustaran modelos logit, para finalmente comparar los resultados de cada modelo y elegir el de mejor performance contra el estadístico de prueba (% de aciertos).

Valores faltantes

Gráfica no. 1 (Valores faltantes)

Análisis univariado

  • Observamos la distribución desbalanceada de los registros a clásificar, en donde Fully Paid representa el 79.23% de la respuesta dicotómica.
## 
## Charged Off  Fully Paid 
##        7103       27106

Código y salida de consola no. 1 (identificando datos desbalanceados)

Inicialmente pasamos a binario el pago (Fully Paid) o el default (Charged Off) con un 1 y un 0 respectivamente.

Análisis univariado variables nominales y ordinales

Gráfica no. 2 (descriptivos de nuestras variables)

  1. Purpose

Por un lado, se unifica el valor de la variable “Other” y “other” en purpose con la funcion tolower(), y por otro, se valorará en el ajuste del modelo la reducción de dimensiones en Train_copy

##  [1] "debt consolidation"   "home improvements"    "other"               
##  [4] "medical bills"        "take a trip"          "business loan"       
##  [7] "buy a car"            "buy house"            "major_purchase"      
## [10] "small_business"       "moving"               "vacation"            
## [13] "wedding"              "educational expenses" "renewable_energy"

Gráfica no. 3 (descriptivo variable purpose)

Análisis univariado y agrupación grafica de variables continuas

Para el modelo de regresión logistica se plantean tres escenarios:

  • Modelado con toda la muestra.
  • Modelado con una muestra reducida (filtro en dos variables continuas)
  • Modelado con una muestra aun más reducida (filtro en x variables continuas)

Todos, con su respectivo Train y Test, para la validación cruzada por medio del estadístico PRESS y el Cp de Mallow así como la validación cruzada por k-folds.

Para el modelado con la submuestra, se requiere un análisis estadístico univariado, bivariado y multivariado que complemente la perdida de información. Para esto y dado que son varias variables continuas, probablemente no tenga sentido meter todas en un solo gráfico de boxplot, por lo que buscamos rangos similares para segmentar en 5 grupos para poderapreciar correctamente las distribuciones.

1er grupo de análisis: Years.of.Credit.History, Number.of.Open.Accounts y Months.since.last.delinquent

Gráfica no. 4 (distribución de variables)

Con la aterior gráfica podemos: Descartar patrones de cumplimiento por las variables Years.of.Credit.History, Number.of.Open.Accounts y Months.since.last.delinquent. Apreciar la presencia de presuntos valores atípicos en las variables Years.of.Credit.History, Number.of.Open.Accounts y Months.since.last.delinquent.

Para esta variable no se propone ningún filtro de valores presuntamente atípicos.

  • Análisis particular de Years.of.Credit.History

Visualizamos los cuartiles de la variable Years.of.Credit.History

## [1] "Primer cuartil"
##  25% 
## 14.4 
## [1] "Segundo cuartil"
##  50% 
## 17.8 
## [1] "Tercer cuartil"
##  75% 
## 22.7 
## [1] "Cuarto cuartil"
## 100% 
## 59.6

Código y salida de consola no. 2 (cuantiles variable Years.of.Credit.History)

Destacar que el 75% de los valores del vector Current.Loan.Amount son menores o iguales a 22.7, mientras que el valor máximo es 59.6. El número de observaciones en el 4to cuartil es de 8429, por lo que un filtro eliminando toda esta submuestra nos haría perder una buena parte de la muestra. Por lo que decidimos hacer un análisis más a fondo para encontrar el punto en donde solo filtremos los valores que sean más extremos.

Con el apoyo visual de la siguiente gráfica pudimos decidir filtrar todas aquellas observaciones de la variable Years.of.Credit.History que sean mayores a 40. De esta forma, eliminariamos 401 variables de la muestra, representando un 1.17% de la misma.

## [1] 401

Gráfica no. 5 (distribución de variables)

Para esta variable se propone el filtro de valores presuntamente atípicos (Years.of.Credit.History < 40).

  • Análisis particular de Number.of.Open.Accounts

Visualizamos los cuartiles para Number.of.Open.Accounts

quantiles_("Number.of.Open.Accounts")
## [1] "Primer cuartil"
## 25% 
##   8 
## [1] "Segundo cuartil"
## 50% 
##  11 
## [1] "Tercer cuartil"
## 75% 
##  14 
## [1] "Cuarto cuartil"
## 100% 
##   49

Código y salida de consola no. 3 (cuantiles variable Number.of.Open.Accounts)

Destacar que el 75% de los valores del vector Number.of.Open.Accounts son menores o iguales a 14 cuentas abiertas. El número de observaciones en el 4to cuartil es de 7793, por lo que un filtro eliminando toda esta submuestra nos haría perder una buena parte de la muestra. Por lo que decidimos hacer un análisis más a fondo para encontrar el punto en donde solo filtremos los valores que sean más extremos.

Con el apoyo visual de la siguiente gráfica pudimos decidir filtrar todas aquellas observaciones de la variable Years.of.Credit.History que sean mayores a 30 De esta forma, eliminariamos 152 variables de la muestra, representando un 0.44% de la misma.

Gráfica no. 6 (distribución de variables)

De la anterior gráfica podríamos hablar de un patron, en donde podríamos hablar de que si el cliente presenta más de 50 unidades en la variable Number.of.Open.Accounts, la probabilidad de Fully Paid sería 100%.

Para esta variable se propone el filtro de valores presuntamente atípicos (Years.of.Credit.History < 30).

  • Months.since.last.delinquent

Visualizamos los cuartiles para Months.since.last.delinquent

quantiles_("Months.since.last.delinquent")
## [1] "Primer cuartil"
##  25% 
## 16.5 
## [1] "Segundo cuartil"
##  50% 
## 31.7 
## [1] "Tercer cuartil"
## 75% 
##  51 
## [1] "Cuarto cuartil"
##  100% 
## 178.1

Código y salida de consola no. 4 (cuantiles variable Number.of.Open.Accounts)

Destacar que el 75% de los valores del vector Months.since.last.delinquent son menores o iguales a 51 meses, mientras que el valor máximo es 178. El número de observaciones en el 4to cuartil es de 8536, por lo que un filtro eliminando toda esta submuestra nos haría perder una buena parte de la muestra. Por lo que decidimos hacer un análisis más a fondo para encontrar el punto en donde solo filtremos los valores que sean más extremos.

Con el apoyo visual de la siguiente gráfica pudimos decidir filtrar todas aquellas observaciones de la variable Months.since.last.delinquent que sean mayores a 51 De esta forma, eliminariamos 31 variables de la muestra, representando un 0.09% de la misma.

Gráfica no. 7 (distribución de variables)

Para esta variable se propone el filtro de valores presuntamente atípicos (Years.of.Credit.History < 85).

2do grupo: Maximum.Open.Credit y Current.Loan.Amount

Gráfica no. 8 (distribución de variables)

Para ambas variables, se vuelve caso de estudio análizar los subgrupos de outliers que se pueden visualizar en la gráfica con la finalidad de evaluar patrones de cumplimiento o la permanencia de estos registros en el ajuste del modelo.

  • Análisis particular de la variable Current.Loan.Amount

Visualizamos los cuartiles de la variable Current.Loan.Amount

## [1] "Primer cuartil"
##      25% 
## 186337.5 
## [1] "Segundo cuartil"
##      50% 
## 324302.7 
## [1] "Tercer cuartil"
##      75% 
## 544016.2 
## [1] "Cuarto cuartil"
##  100% 
## 1e+08

Código y salida de consola no. 5 (cuantiles variable Current.Loan.Amount)

En este punto cabe destacar que el 75% de los valores del vector Current.Loan.Amount son menores o iguales a 544,016.2.

Dado que parece que los valores del cuarto cuartil son tan extremos para sugerirnos filtrarlos del estudio, pero en conteo representan 8,551 observaciones, se decide hacer un estudio de la distribución de los datos en el cuarto cuartil para evaluar si se pueden recuperar algunas observaciones. Es claro que un modelo no se va ajustar apropiadamente a registros con valores de cantidad de deuda actual de 500 mil y de 90 millones en una de las variables regresoras, y si se ajusta, no será el mejor modelo o la variable perdera significancia estadística en el modelo.

En el análisis del cuarto cuartil, que son valores mayores a 544,016.2, se puede observar la siguiente distribución de los datos con ayuda de un gráfico de violin:

## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Gráfica no. 9 (distribución de variables)

Y dado que los valores de la izquierda de la curva bimodal no son tan extremos como los de la parte derecha, nos planteamos la idea de separar la gráfica anterior para un análisis más a fondo. Los valores de la curva izquierda bimodal toman la siguiente distribución, con valor mínimo de 544,016.2 y máximo de 24.5 M, como no lo indica la anterior gráfia, que en conteo son 3,839 observaciones y tienen la siguiente distribución. Por su parte, Los valores de la curva derecha bimodal toman la siguiente distribución, con valor mínimo de 50M y máximo de 24l5 M, como no lo indica la anterior gráfia, que en conteo son 4,712 observaciones y tienen la siguiente distribución. Gráfica no. 10 (distribución de variables)

Con la gráfica anterior podríamos afirmar que cualquier registro que tenga un valor mayor a 50M en la variable Current.Loan.Amount adoptara un 1 (o Fully Paid) en la variable respuesta, por lo que podríamos quitar filtrar dichos registros con estos valores en la muestra para mejorar el ajuste, e incluirlos en un filtro posterior a la predicción del modelo ajustado.

Por lo que en conclusión, en el análisis univariado de la variable Current.Loan.Amount y al poder observar la cota superior aproximada a la que debemos delimitarla para restringir valores extremos, con la finalidad de generar un mejor ajuste, el modelo se ajustara con todas aquellas obervaciones que sean menores o iguales a 800,000 (por redondeo), estableciendo en este punto el filtro propuesto pora esta variable, que representaran un 86.2% de las obervaciones de esta variable y que adoptan la siguiente distribución.

Gráfica no. 10 (distribución de variables)

La idea de este análisis particular es por un lado acotar la muestra eliminando valores extremos, y establecer un filtro de clásificación posterior a la predicción con el modelo ajustado. Por lo que el resto de variables que superen este limite establecido a críterio para la variable Current.Loan.Amount, en el filtro manual por análisis exploratorio posterior a la predicción del modelo ajustado, serán calificadas automaticamente como Fully Paid (1).

  • Análisis particular de la variable Maximum.Open.Credit

Dada la gráfica de comparación del grupo 2 (referenciar), se presume que si separamos los valores de Maximum.Open.Credit por Fully Paid (1) o Charged Off (0), encontraremos diferencias importantes en la distribución.

plot_1 = ggplot(filter(Train_copy_continuas, Loan.Status == 1), aes(y=1, x=Maximum.Open.Credit))+
  geom_jitter(aes(color=Loan.Status))+
  geom_violin(alpha=0.5) +
  geom_boxplot(width = 0.1, fill = "white", alpha = 0.5)+
  scale_y_continuous(NULL, labels = NULL)+
  scale_x_continuous(breaks = c(0, 200000000, 400000000, 600000000, 800000000),
                     labels = c("0", "200M", "400M", "600M", "800M"))+
  scale_color_manual(values = c("deepskyblue"))+
  ggtitle("Variable Maximum.Open.Credit para clientes con Loan.Status = Fully Paid")+
  theme_bw()

plot_2 = ggplot(filter(Train_copy_continuas, Loan.Status == 0), aes(y=1, x=Maximum.Open.Credit))+
  geom_jitter(aes(color=Loan.Status))+
  geom_violin(alpha=0.5) +
  geom_boxplot(width = 0.1, fill = "white", alpha = 0.5)+
  scale_y_continuous(NULL, labels = NULL)+
  scale_x_continuous(breaks = c(0, 25000000, 50000000, 75000000, 100000000),
                     labels = c("0", "25M", "50M", "75M", "100M"))+
  ggtitle("Variable Maximum.Open.Credit para clientes con Loan.Status = Charged Off")+
  theme_bw()

plot_3 = ggplot(Train_copy_continuas, aes(y=1, x=Maximum.Open.Credit))+
  geom_jitter(aes(color=Loan.Status))+
  geom_violin(alpha=0.5) +
  geom_boxplot(width = 0.1, fill = "white", alpha = 0.5)+
  scale_y_continuous(NULL, labels = NULL)+
  scale_x_continuous(breaks = c(0, 200000000, 400000000, 600000000, 800000000),
                     labels = c("0", "200M", "400M", "600M", "800M"))+
  ggtitle("Variable Maximum.Open.Credit")+
  theme_bw()

grid.arrange(plot_3, plot_2, plot_1, ncol = 1)

Gráfica no. 11 (distribución de variables)

Por un lado el valor máximo de la variable Maximum.Open.Credit cuando la variable Loan.Status es igual a Fully Paid (1) es de 798M, por el otro este mismo valor máximo pero para cuando la variable Loan.Status es igual a Charged Off (0) es de 98M. Con lo anterior podríamos establecer otro filtro manual por análisis exploratorio posterior a la predicción del modelo ajustado en donde todos los registros que adopen un valor superior a 100M Maximum.Open.Credit serán clásificados como Fully Paid (1).

Para esta variable se propone el filtro de valores presuntamente atípicos (Maximum.Open.Credit < 800K).

3er grupo: - Análisis particular de la variable Annual.Income

Visualizando los cuantiles de Annual.Income.

quantiles_("Annual.Income")
## [1] "Primer cuartil"
##      25% 
## 914336.3 
## [1] "Segundo cuartil"
##     50% 
## 1245126 
## [1] "Tercer cuartil"
##     75% 
## 1726247 
## [1] "Cuarto cuartil"
##     100% 
## 30838994

Código y salida de consola no. 6 (cuantiles variable Annual.Income)

Destacar que el 75% de los valores del vector Annual.Income son menores o iguales a 1,726,247 El número de observaciones en el 4to cuartil es de 8551 con un valor máximo de 30,838,994, por lo que un filtro eliminando toda esta submuestra nos haría perder una buena parte de la muestra. Por lo que decidimos hacer un análisis más a fondo para encontrar el punto en donde solo filtremos los valores que sean más extremos.

Con el apoyo visual de la anterior gráfica podemos decidir filtrar todas aquellas observaciones de la variable Annual.Income que sean mayores a 4000000 De esta forma, para el filtro de las sumuestras eliminariamos 572 variables de la muestra, representando un 1.67% de la misma.

Gráfica no. 12 (distribución de variables)

Para esta variable no se encuentran patrones de cumplimiento y se propone el filtro de valores presuntamente atípicos (Annual.Income < 4M).

4to grupo: - Análisis particular de la variable Current.Credit.Balance

quantiles_("Current.Credit.Balance")
## [1] "Primer cuartil"
##    25% 
## 100092 
## [1] "Segundo cuartil"
##      50% 
## 185212.3 
## [1] "Tercer cuartil"
##      75% 
## 327180.4 
## [1] "Cuarto cuartil"
##    100% 
## 7140733

Código y salida de consola no. 7 (cuantiles variable Current.Credit.Balance)

En este punto cabe destacar que el 75% de los valores del vector Current.Credit.Balance son menores o iguales a 327,180.4 El número de observaciones en el 4to cuartil es de 8,552, por lo que un filtro eliminando toda esta submuestra nos haría perder una buena parte de la muestra. Por lo que decidimos hacer un análisis más a fondo para encontrar el punto en donde solo filtremos los valores que sean más extremos.

Con el apoyo visual de la siguiente gráfica pudimos decidir filtrar todas aquellas observaciones de la variable Current.Credit.Balance que sean mayores a 1000000 De esta forma, eliminariamos 588 variables de la muestra, representando un 1.71% de la misma.

Gráfica no. 13 (distribución de variables)

Para esta variable no se encuentran patrones de cumplimiento y se propone el filtro de valores presuntamente atípicos (Current.Credit.Balance < 1M).

  • Análisis particular de la variable Monthly.Debt

Visualizando los quantiles de Monthly.Debt

quantiles_("Monthly.Debt")
## [1] "Primer cuartil"
##      25% 
## 10807.22 
## [1] "Segundo cuartil"
##      50% 
## 16860.44 
## [1] "Tercer cuartil"
##      75% 
## 24554.97 
## [1] "Cuarto cuartil"
##     100% 
## 229056.4

Código y salida de consola no. 8 (cuantiles variable Monthly.Debt)

En este punto cabe destacar que el 75% de los valores del vector Monthly.Debt son menores o iguales a 24,554.97 El número de observaciones en el 4to cuartil es de 8,553, por lo que un filtro eliminando toda esta submuestra nos haría perder una buena parte de la muestra. Por lo que decidimos hacer un análisis más a fondo para encontrar el punto en donde solo filtremos los valores que sean más extremos.

Con el apoyo visual de la siguiente gráfica pudimos decidir filtrar todas aquellas observaciones de la variable Current.Credit.Balance que sean mayores a 50,000 De esta forma, eliminariamos 781 variables de la muestra, representando un 2.28% de la misma.

plot_1 = ggplot(filter(Train_copy_continuas, Monthly.Debt <= 50000), aes(y=1, x=Monthly.Debt))+
  geom_jitter(aes(color=Loan.Status))+
  geom_violin(alpha=0.5) +
  geom_boxplot(width = 0.1, fill = "white", alpha = 0.5)+
  scale_y_continuous(NULL, labels = NULL)+
  scale_x_continuous(breaks = c(0, 10000, 20000, 30000, 40000, 50000),
                     labels = c("0", "10K", "20K", "30K", "40K", "50K"))+
  ggtitle("Variable Monthly.Debt posterior al filtro (valores < 50000)")+
  theme_bw()

plot_2 = ggplot(Train_copy_continuas, aes(y=1, x=Monthly.Debt))+
  geom_jitter(aes(color=Loan.Status))+
  geom_violin(alpha=0.5) +
  geom_boxplot(width = 0.1, fill = "white", alpha = 0.5)+
  scale_y_continuous(NULL, labels = NULL)+
  scale_x_continuous(breaks = c(0, 25000, 50000, 100000, 150000, 200000),
                     labels = c("0", "25K", "50K", "100K", "150K", "200K"))+
  ggtitle("Variable Annual.Income previo al filtro")+
  theme_bw()

grid.arrange(plot_2, plot_1, ncol = 1)

Gráfica no. 14 (distribución de variables)

Para esta variable se encuentran patrones de cumplimiento en aquellos clientes con valores en Monthly.Debt mayores a 125K, por lo que esta observación pasa a formar parte del filtro manual por análisis exploratorio posterior a la predicción del modelo ajustado en donde todos los registros que adopen un valor superior a 125K Monthly.Debt serán clásificados como Fully Paid (1). Además, se propone el filtro de valores presuntamente atípicos (Current.Credit.Balance < 1M).

6to grupo: - Análisis particular de la variable Credit.Score

La situación de la distribución de los valores parece ser un poco similar al caso de la variable Current.Loan.Amount, por lo que se buscara proponer filtrar los registros de aquellas observaciones extremas para la variable Credit.Score en estudio. Cuando la media el score crediticio se encuentra en 1048.483, los valores de esta variable mayores a 5mil empiezan a perder mucho sentido, generandonos dudas sobre si estos datos se recopilaron apropiadamente o son inexactos como para ponerles un tope.

Por un lado se análizan los cuartiles del vector y se elaboran dos gráficas de cajas y bigotes más una capa de violin, además de un histógrama: una para valores que se encuentre en el primer, segundo y tercer cuartil y otra para el cuarto cuartil.

quantiles_("Credit.Score")
## [1] "Primer cuartil"
## 25% 
## 702 
## [1] "Segundo cuartil"
## 50% 
## 721 
## [1] "Tercer cuartil"
## 75% 
## 738 
## [1] "Cuarto cuartil"
## 100% 
## 7509

Código y salida de consola no. 9 (cuantiles variable Credit.Score)

train_selected = Train_copy_continuas %>% filter(Credit.Score <= 738) %>% select(Credit.Score, Loan.Status)
train_long_form8 = gather(train_selected, key = "variable", value = "valor", -Loan.Status)

plot_1 = ggplot(train_long_form8, aes(y=variable, x=valor))+
  geom_jitter(aes(color=Loan.Status))+
  geom_violin(alpha=0.5) +
  geom_boxplot(width = 0.1, fill = "white", alpha = 0.5)+
  # geom_jitter()+ 
  stat_summary(fun=mean, colour="darkred", geom="point",
               shape=18, size=3, show.legend=FALSE)+
  scale_y_discrete(NULL)+
  ggtitle(glue("Credit.Score posterior al filtro (valores menores o iguales a 753)"))+
  theme_bw()

train_selected = Train_copy_continuas %>% select(Credit.Score, Loan.Status)
train_long_form9 = gather(train_selected, key = "variable", value = "valor", -Loan.Status)

plot_2 = ggplot(train_long_form9, aes(y=variable, x=valor))+
  geom_jitter(aes(color=Loan.Status))+
  geom_violin(alpha=0.5) +
  geom_boxplot(width = 0.1, fill = "white", alpha = 0.5)+
  # geom_jitter()+ 
  stat_summary(fun=mean, colour="darkred", geom="point",
               shape=18, size=3, show.legend=FALSE)+
  scale_y_discrete(NULL)+
  ggtitle(glue("Credit.Score previo al filtro"))+
  theme_bw()

grid.arrange(plot_2, plot_1, ncol = 1)

Gráfica no. 15 (distribución de variables)

train_selected = Train_copy_continuas %>% select(Credit.Score, Loan.Status)
train_long_form9 = gather(train_selected, key = "variable", value = "valor", -Loan.Status)

plot_1 = ggplot(filter(train_long_form9, Loan.Status == 1), aes(y=variable, x=valor))+
  geom_jitter(aes(color=Loan.Status))+
  geom_violin(alpha=0.5) +
  geom_boxplot(width = 0.1, fill = "white", alpha = 0.5)+
  # geom_jitter()+ 
  stat_summary(fun=mean, colour="darkred", geom="point",
               shape=18, size=3, show.legend=FALSE)+
  scale_y_discrete(NULL)+
  scale_color_manual(values = c("deepskyblue"))+
  ggtitle(glue("Credit.Score para clientes con Loan.Status = 1"))+
  theme_bw()


plot_2 = ggplot(filter(train_long_form9, Loan.Status == 0), aes(y=variable, x=valor))+
  geom_jitter(aes(color=Loan.Status))+
  geom_violin(alpha=0.5) +
  geom_boxplot(width = 0.1, fill = "white", alpha = 0.5)+
  # geom_jitter()+ 
  stat_summary(fun=mean, colour="darkred", geom="point",
               shape=18, size=3, show.legend=FALSE)+
  scale_y_discrete(NULL)+
  ggtitle(glue("Credit.Score para clientes con Loan.Status = 0"))+
  theme_bw()

grid.arrange(plot_2, plot_1, ncol = 1)

Gráfica no. 16 (distribución de variables) Para esta variable si se encuentran patrones claros de incumplimiento en aquellos clientes con valores en Credit.Score mayores a 6K, por lo que esta observación pasa a formar parte del filtro manual por análisis exploratorio posterior a la predicción del modelo ajustado en donde todos los registros que adopen un valor superior a 6K Credit.Score serán clásificados como Charged off (0). Además, se propone el filtro de valores presuntamente atípicos (Current.Credit.Balance < 753).

7mo grupo: Tax.Liens y Bankruptcies

Se decide no emplear filtros para este grupo.

A resaltar del análisis univariado y bivariado:

EN EL PERIODO DEL CREDITO - Son más los clientes que solicitan un crédito a corto plazo (70%) que los que solicitan a LP (30%) - Aquellos clientes con default son el grupo predominante en el gpo de clientes que solicitaron un crédito a largo plazo - La mediana del current loan es más alta para clientes con creditos CP que a LP, corroborar la media porque se notan outliers altos en CP. - Son más los clientes con una hipóteca que piden crédito a LP que a CP, que los clientes que rentan su vivienda con créditos a CP que a LP. (variacion > 10%) - La media de la deuda actual del cliente es mayor para los clientes que solicitan un crédito a LP, que uno a CP, lo cual tiene logica de negocio. - La media del credit score es mayor para los clientes que solicitan crédito a CP que a LP.

EN LOS AÑOS DE TRABAJO DEL CLIENTE: - El grupo que predomina es el de > 10 años de trabajo con un 35%, seguido de 2 años con un 8.5%

EN EL DUEÑO DE LA VIVIENDA: - Destaca el grupo de clientes con hipóteca con un 51%, seguido de Renta con un 39% y solo casa propia con un 9% - Hay dos factores que se podrían unificar: have mortgage & home mortgage, aunque la prop del primeor es de 0.2% por lo que no vale la pena

EN EL PROPOSITO DEL CRÉDITO: - Destaca con un 73% el proposito de consolidación de la deuda como proposito declarado.

EN LAS BANCARROTAS: - El 65% de los clientes declara nunca haber caído en bancarrota, le sigue el 25% con al menos una bancarrota. - El grupo, por proposito del crédito, que predomina en una bancarrota declarada es aquel grupo que declara solicitar el crédito para “moving” - La mediana del numero máximo de creditos abiertos se relaciona negativamente con el número de bancarrotas. Entre más bancarrotas es menor el numero de créditos abiertos.

EN LA DEUDA ACTUAL DEL CLIENTE: - La mediana de la deuda tiene una relación negativa con el aumento en el credit scoring, a mayor credit score menor es la mediana (falta corroborar la media dado outliers en altos credit scores) - la mediana sigue una relacion positiva con el ingreso anual (corroborar media) - la mediana sigue una relacion positiva con la deuda mensual (corroborar media) - la mediana sigue una relacion positiva con el balance crediticio (corroborar media)

EN LOS AÑOS DE HISTORIAL CREDITICIO:

  • La mediana de los años mantiene una relacion positiva con el balance crediticio

EN EL BALANCE ACTUAL DEL CREDITO: - La mediana del balance mantiene una relacion positiva con el maximo de creditos abiertos.

EN EL CREDIT SCORING: - Todos aquellos clientes que presentan un credit score > 5,800, también presentan el valor de Charged off en la variable de respuesta binaria Loan.Status.

  • Configuración del filtro manual por análisis exploratorio posterior a la predicción del modelo ajustado:

La variable Loan.Status adoptara el valor de 1 (Fully Paid) cuando: - El registro presente más de 50 unidades en la variable Number.of.Open.Accounts. - El registro presente un valor mayor a 50M en la variable Current.Loan.Amount - El registro presente un valor mayor a 100M en la variable Maximum.Open.Credit - El registro presente un valor mayor a 125K en la variable Monthly.Debt

La variable Loan.Status adoptara el valor de 0 (Charged off) cuando: - El registro presente un valor mayor a 6K en la variable Credit.Score

En este apartado generamos los nuevos datasets a estudiar en siguientes scripts

  • Modelado con toda la muestra.
  • Modelado con una submuestra (filtro en 11 variables continuas)

Muestra completa

write_csv(Train_copy, "../datasets/muestra_completa.csv")
Train_copy_1_continues = Train_copy %>% select(Current.Loan.Amount, Credit.Score, Annual.Income, Monthly.Debt, Years.of.Credit.History, Months.since.last.delinquent, Number.of.Open.Accounts, Current.Credit.Balance, Maximum.Open.Credit, Bankruptcies, Tax.Liens)

chart.Correlation(select(Train_copy_1_continues, -c(Tax.Liens)), histogram=TRUE, pch=19, main = "Matriz de correlaciones con histógrama muestra completa")

Gráfica no. 16 (correlaciones muestra completa)

Muestra reducida no. 1, en donde se propondrá un modelo con el 32% de la muestra original.

Train_copy_2 = Train_copy %>% filter(Current.Loan.Amount <= 80000000, Credit.Score <= 753, Maximum.Open.Credit <= 80000000, Years.of.Credit.History <= 40, Number.of.Open.Accounts <= 30, Months.since.last.delinquent <= 30, Current.Loan.Amount <= 80000000, Annual.Income <= 4000000, Current.Credit.Balance <= 1000000, Monthly.Debt <= 50000, Credit.Score <= 753)

print(glue("Train_copy en un inicio tuvó {format(nrow(Train_copy), big.mark = ',')} obs"))
## Train_copy en un inicio tuvó 34,209 obs
print(glue("Train_copy_2 ahora tiene {format(nrow(Train_copy_2), big.mark = ',')} obs"))
## Train_copy_2 ahora tiene 12,368 obs
print(glue("Se redujo el dataset en un {(1 - (nrow(Train_copy_2)/nrow(Train_copy)))*100 }%"))
## Se redujo el dataset en un 63.8457715805782%
write_csv(Train_copy_2, "../datasets/muestra_reducida_2.csv")
Train_copy_1_continues = Train_copy_2 %>% select(Current.Loan.Amount, Credit.Score, Annual.Income, Monthly.Debt, Years.of.Credit.History, Months.since.last.delinquent, Number.of.Open.Accounts, Current.Credit.Balance, Maximum.Open.Credit, Bankruptcies, Tax.Liens)

chart.Correlation(select(Train_copy_1_continues, -c(Tax.Liens)), histogram=TRUE, pch=19, main = "Matriz de correlaciones con histógrama muestra reducida no. 2")

Gráfica no. 17 (correlaciones submuestra)

La continuación de este proyecto, que es la parte del modelado, continuará en los rmarkdown modelo 1 y modelo 2. En cada uno de estos rmarkdowns donde se plantea ajustar el mejor modelo dada la submuestra analizada, separando Train y Test, empleando selección de variables, validación cruzada y bootstrap, finalizando con generar un archivo RData de cada modelo así como un diagnostico con el estadístico PRESS.

La idea principal de esto es llevar cada modelo a una validación cruzada simulada con la muestra Test que será evaluada en el proyecto final de clase.